﻿// ----------------------------------------------------------------------------------
// Microsoft Developer & Platform Evangelism
// 
// Copyright (c) Microsoft Corporation. All rights reserved.
// 
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
// EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES 
// OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
// ----------------------------------------------------------------------------------
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
// ----------------------------------------------------------------------------------

namespace Microsoft.Samples.WindowsPhoneCloud.StorageClient
{
    using System;
    using System.Globalization;
    using System.IO;
    using System.Net;
    using System.Net.Browser;
    using Microsoft.Samples.WindowsPhoneCloud.StorageClient.Credentials;

    public class CloudBlobContainer : ICloudBlobContainer
    {
        public CloudBlobContainer(StorageClient.Credentials.IStorageCredentials credentials)
        {
            this.StorageCredentials = credentials;
        }

        public IStorageCredentials StorageCredentials { get; set; }

        public void CreateContainer(Uri uri, Action<CloudOperationResponse<bool>> callback)
        {
            var request = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(new Uri(string.Format(CultureInfo.InvariantCulture, "{0}?restype=container&timeout=10000", uri)));

            request.Method = "PUT";
            request.Headers["x-ms-version"] = "2009-09-19";
            request.Headers["x-ms-blob-type"] = "BlockBlob";

            request.BeginGetRequestStream(
                ar =>
                {
                    this.StorageCredentials.SignRequest(request, 0);
                    request.BeginGetResponse(
                        asyncResult =>
                        {
                            var req = (HttpWebRequest)asyncResult.AsyncState;
                            if (req.HaveResponse)
                            {
                                try
                                {
                                    var res = (HttpWebResponse)req.EndGetResponse(asyncResult);
                                    if (res.StatusCode == HttpStatusCode.Created)
                                    {
                                        callback(new CloudOperationResponse<bool>(true, null));
                                    }
                                    else
                                    {
                                        callback(new CloudOperationResponse<bool>(false, new Exception(string.Format(CultureInfo.InvariantCulture, "Error creating container: {0}", res.StatusDescription))));
                                    }
                                }
                                catch (Exception exception)
                                {
                                    var webException = exception as WebException;
                                    if (webException != null)
                                    {
                                        var resStream = webException.Response.GetResponseStream();
                                        var sr = new StreamReader(resStream);
                                        if (sr.ReadToEnd().Contains("ContainerAlreadyExists"))
                                        {
                                            callback(new CloudOperationResponse<bool>(false, null));
                                        }
                                        else
                                        {
                                            resStream.Position = 0;
                                            callback(new CloudOperationResponse<bool>(false, webException));
                                        }
                                    }
                                    else
                                    {
                                        callback(new CloudOperationResponse<bool>(false, exception));
                                    }
                                }
                            }
                        },
                        request);
                }, 
                request);
        }

        public void CreateContainerIfNotExist(Uri uri, Action<CloudOperationResponse<bool>> callback)
        {
            this.DoesContainerExist(
                uri,
                cloudOperationResponse =>
                {
                    if (cloudOperationResponse.Exception != null)
                    {
                        callback(new CloudOperationResponse<bool>(false, cloudOperationResponse.Exception));
                    }
                    else
                    {
                        if (!cloudOperationResponse.Response)
                        {
                            CreateContainer(uri, callback);
                        }
                        else
                        {
                            callback(new CloudOperationResponse<bool>(true, null));
                        }
                    }
                });
        }

        public void DoesContainerExist(Uri uri, Action<CloudOperationResponse<bool>> callback)
        {
            var request = (HttpWebRequest)WebRequestCreator.ClientHttp.Create(new Uri(string.Format(CultureInfo.InvariantCulture, "{0}?restype=container&timeout=10000", uri)));

            request.Method = "GET";
            request.BeginGetResponse(
                asyncResult =>
                {
                    var req = (HttpWebRequest)asyncResult.AsyncState;
                    if (req.HaveResponse)
                    {
                        try
                        {
                            var res = (HttpWebResponse)req.EndGetResponse(asyncResult);
                            callback(new CloudOperationResponse<bool>(true, null));
                        }
                        catch (Exception exception)
                        {
                            var webException = exception as WebException;

                            if (webException != null)
                            {
                                var resStream = webException.Response.GetResponseStream();
                                var sr = new StreamReader(resStream);
                                var responseContent = sr.ReadToEnd();
                                if (responseContent.Contains("ResourceNotFound"))
                                {
                                    callback(new CloudOperationResponse<bool>(false, null));
                                }
                                else
                                {
                                    callback(new CloudOperationResponse<bool>(false, exception));
                                }
                            }
                            else
                            {
                                callback(new CloudOperationResponse<bool>(false, exception));
                            }
                        }
                    }
                },
                request);
        }
    }
}
